"""
Provider管理器

负责管理各个云盘provider的生命周期，实现内部管理逻辑的封装。
"""

from typing import Dict, List, Optional, Any, Callable
import logging
import threading
import time
from concurrent.futures import ThreadPoolExecutor, Future
from .base import BaseCloudProvider, CloudFile, UploadResult, DownloadResult
from .factory import CloudProviderFactory


class ProviderSession:
    """Provider会话管理"""
    
    def __init__(self, provider: BaseCloudProvider, mount_point: str):
        self.provider = provider
        self.mount_point = mount_point
        self.created_at = time.time()
        self.last_access = time.time()
        self.access_count = 0
        self.is_active = False
        self.login_status = False
        self.error_count = 0
        self.max_errors = 5
        
        # 线程安全锁
        self._lock = threading.RLock()
    
    def access(self):
        """记录访问"""
        with self._lock:
            self.last_access = time.time()
            self.access_count += 1
    
    def mark_error(self):
        """标记错误"""
        with self._lock:
            self.error_count += 1
    
    def reset_errors(self):
        """重置错误计数"""
        with self._lock:
            self.error_count = 0
    
    def is_healthy(self) -> bool:
        """检查会话是否健康"""
        with self._lock:
            return self.error_count < self.max_errors and self.login_status
    
    def get_stats(self) -> Dict[str, Any]:
        """获取会话统计信息"""
        with self._lock:
            return {
                "mount_point": self.mount_point,
                "created_at": self.created_at,
                "last_access": self.last_access,
                "access_count": self.access_count,
                "is_active": self.is_active,
                "login_status": self.login_status,
                "error_count": self.error_count,
                "is_healthy": self.is_healthy()
            }


class ProviderManager:
    """Provider管理器
    
    负责管理各个云盘provider的生命周期，包括：
    1. Provider的创建、登录、注销
    2. 会话管理和健康检查
    3. 错误处理和重试机制
    4. 性能监控和统计
    """
    
    def __init__(self, max_workers: int = 5):
        """
        初始化Provider管理器
        
        Args:
            max_workers: 最大工作线程数
        """
        self.logger = logging.getLogger(self.__class__.__name__)
        self.factory = CloudProviderFactory()
        
        # Provider会话管理
        self._sessions: Dict[str, ProviderSession] = {}
        self._sessions_lock = threading.RLock()
        
        # 线程池
        self._executor = ThreadPoolExecutor(max_workers=max_workers)
        
        # 健康检查
        self._health_check_interval = 300  # 5分钟
        self._health_check_thread = None
        self._stop_health_check = threading.Event()
        
        # 统计信息
        self._stats = {
            "total_requests": 0,
            "successful_requests": 0,
            "failed_requests": 0,
            "total_providers": 0,
            "active_providers": 0
        }
        self._stats_lock = threading.Lock()
    
    def create_provider(self, mount_point: str, provider_type: str, 
                       config: Dict[str, Any], auto_login: bool = True) -> bool:
        """
        创建并注册provider
        
        Args:
            mount_point: 挂载点
            provider_type: provider类型
            config: 配置信息
            auto_login: 是否自动登录
            
        Returns:
            bool: 创建是否成功
        """
        try:
            with self._sessions_lock:
                # 检查是否已存在
                if mount_point in self._sessions:
                    self.logger.warning(f"Provider已存在: {mount_point}")
                    return False
                
                # 创建provider实例
                provider = self.factory.create_provider(provider_type, config)
                if not provider:
                    self.logger.error(f"创建provider失败: {provider_type}")
                    return False
                
                # 创建会话
                session = ProviderSession(provider, mount_point)
                
                # 自动登录
                if auto_login:
                    if provider.login():
                        session.login_status = True
                        session.is_active = True
                        self.logger.info(f"Provider登录成功: {mount_point}")
                    else:
                        self.logger.error(f"Provider登录失败: {mount_point}")
                        return False
                
                # 注册会话
                self._sessions[mount_point] = session
                
                # 更新统计
                with self._stats_lock:
                    self._stats["total_providers"] += 1
                    if session.is_active:
                        self._stats["active_providers"] += 1
                
                # 启动健康检查
                self._start_health_check()
                
                self.logger.info(f"成功创建provider: {mount_point} -> {provider_type}")
                return True
                
        except Exception as e:
            self.logger.error(f"创建provider失败: {e}")
            return False
    
    def remove_provider(self, mount_point: str) -> bool:
        """
        移除provider
        
        Args:
            mount_point: 挂载点
            
        Returns:
            bool: 移除是否成功
        """
        try:
            with self._sessions_lock:
                if mount_point not in self._sessions:
                    self.logger.warning(f"Provider不存在: {mount_point}")
                    return False
                
                session = self._sessions[mount_point]
                
                # 登出provider
                try:
                    session.provider.logout()
                except Exception as e:
                    self.logger.warning(f"Provider登出失败: {e}")
                
                # 移除会话
                del self._sessions[mount_point]
                
                # 更新统计
                with self._stats_lock:
                    self._stats["total_providers"] -= 1
                    if session.is_active:
                        self._stats["active_providers"] -= 1
                
                self.logger.info(f"成功移除provider: {mount_point}")
                return True
                
        except Exception as e:
            self.logger.error(f"移除provider失败: {e}")
            return False
    
    def get_provider(self, mount_point: str) -> Optional[BaseCloudProvider]:
        """
        获取provider实例
        
        Args:
            mount_point: 挂载点
            
        Returns:
            Optional[BaseCloudProvider]: provider实例
        """
        with self._sessions_lock:
            session = self._sessions.get(mount_point)
            if session and session.is_healthy():
                session.access()
                return session.provider
            return None
    
    def execute_with_provider(self, mount_point: str, operation: str, 
                            func: Callable, *args, **kwargs) -> Any:
        """
        使用provider执行操作，包含错误处理和重试机制
        
        Args:
            mount_point: 挂载点
            operation: 操作名称
            func: 要执行的函数
            *args: 函数参数
            **kwargs: 函数关键字参数
            
        Returns:
            Any: 操作结果
        """
        with self._stats_lock:
            self._stats["total_requests"] += 1
        
        session = None
        try:
            with self._sessions_lock:
                session = self._sessions.get(mount_point)
                if not session:
                    raise ValueError(f"Provider不存在: {mount_point}")
                
                if not session.is_healthy():
                    # 尝试重新登录
                    if not self._try_recover_session(session):
                        raise RuntimeError(f"Provider不健康且无法恢复: {mount_point}")
            
            # 执行操作
            session.access()
            result = func(session.provider, *args, **kwargs)
            
            # 重置错误计数
            session.reset_errors()
            
            # 更新统计
            with self._stats_lock:
                self._stats["successful_requests"] += 1
            
            return result
            
        except Exception as e:
            # 记录错误
            if session:
                session.mark_error()
            
            # 更新统计
            with self._stats_lock:
                self._stats["failed_requests"] += 1
            
            self.logger.error(f"执行操作失败 {operation} on {mount_point}: {e}")
            raise
    
    def _try_recover_session(self, session: ProviderSession) -> bool:
        """尝试恢复会话"""
        try:
            self.logger.info(f"尝试恢复会话: {session.mount_point}")
            
            # 重新登录
            if session.provider.login():
                session.login_status = True
                session.is_active = True
                session.reset_errors()
                self.logger.info(f"会话恢复成功: {session.mount_point}")
                return True
            else:
                self.logger.error(f"会话恢复失败: {session.mount_point}")
                return False
                
        except Exception as e:
            self.logger.error(f"恢复会话异常: {e}")
            return False
    
    def _start_health_check(self):
        """启动健康检查线程"""
        if self._health_check_thread is None or not self._health_check_thread.is_alive():
            self._stop_health_check.clear()
            self._health_check_thread = threading.Thread(
                target=self._health_check_loop,
                daemon=True
            )
            self._health_check_thread.start()
            self.logger.info("健康检查线程已启动")
    
    def _health_check_loop(self):
        """健康检查循环"""
        while not self._stop_health_check.wait(self._health_check_interval):
            try:
                self._perform_health_check()
            except Exception as e:
                self.logger.error(f"健康检查异常: {e}")
    
    def _perform_health_check(self):
        """执行健康检查"""
        with self._sessions_lock:
            sessions = list(self._sessions.values())
        
        for session in sessions:
            try:
                if not session.is_healthy():
                    self.logger.warning(f"检测到不健康的会话: {session.mount_point}")
                    
                    # 尝试恢复
                    if self._try_recover_session(session):
                        self.logger.info(f"会话已恢复: {session.mount_point}")
                    else:
                        self.logger.error(f"会话无法恢复: {session.mount_point}")
                        session.is_active = False
                
            except Exception as e:
                self.logger.error(f"健康检查会话失败 {session.mount_point}: {e}")
    
    def list_providers(self) -> List[str]:
        """
        列出所有provider的挂载点
        
        Returns:
            List[str]: 挂载点列表
        """
        with self._sessions_lock:
            return list(self._sessions.keys())
    
    def get_all_sessions(self) -> Dict[str, Dict[str, Any]]:
        """获取所有会话信息"""
        with self._sessions_lock:
            return {
                mount_point: session.get_stats()
                for mount_point, session in self._sessions.items()
            }
    
    def get_stats(self) -> Dict[str, Any]:
        """获取统计信息"""
        with self._stats_lock:
            stats = self._stats.copy()
        
        with self._sessions_lock:
            stats["active_providers"] = sum(
                1 for session in self._sessions.values() 
                if session.is_active
            )
        
        return stats
    
    def shutdown(self):
        """关闭管理器"""
        self.logger.info("正在关闭Provider管理器...")
        
        # 停止健康检查
        self._stop_health_check.set()
        if self._health_check_thread:
            self._health_check_thread.join(timeout=5)
        
        # 关闭所有provider
        with self._sessions_lock:
            for mount_point in list(self._sessions.keys()):
                self.remove_provider(mount_point)
        
        # 关闭线程池
        self._executor.shutdown(wait=True)
        
        self.logger.info("Provider管理器已关闭")
    
    def __enter__(self):
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.shutdown()